﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Topology;
using DotSpatial.Symbology;
using System.Drawing;
using DotSpatial.Projections;
using GeostatisticalTool.Classes;
namespace GeostatisticalTool.Forms
{

   public  class OperationsMap: UserControl
    {

        private IFeatureSet _polygon;
        private IRaster _raster;

        private SplitContainer splitContainer1;
        private Map map1;
        private Button uxZoomIn;
        private Button uxZoomOut;
        private Button uxIdentify;
        private Button uxPan;
        private IFeatureSet cross;
        private IFeatureSet idcross; 
        private IFeatureSet pointSelect; 
        private IFeatureSet poly;
        private double x;

        public double X
        {
            get { return x; }
            set { x = value; }
        }
        private double y;

        public double Y
        {
            get { return y; }
            set { y = value; }
        }
        private double z;
        public double Z
        {
            get { return z; }
            set { z = value; }
        }


        public event EventHandler ChangedCoordinate;
        protected virtual void OnChangedCoordinater(EventArgs e)
        {
            if (ChangedCoordinate != null)
                ChangedCoordinate(this, e);
        }


        double[] valuesMinMax=null;

        public double[] ValuesMinMax
        {
            get { return valuesMinMax; }
            set { valuesMinMax = value; }
        }

       public void SetCoordinates(double x, double y)
       {
                    this.x=x;
                    this.y=y;
                    AddGeometries("cross", GetCross());
                  
       }

        public OperationsMap()
        {
            InitializeComponent();
            map1.MouseClick+=new MouseEventHandler(map1_MouseClick);

        }


        void map1_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //only modify rectangle drawing if function mode is Select
            //  if (_map.FunctionMode != FunctionMode.Select) return;

            Coordinate endPoint = new Coordinate(map1.PixelToProj(e.Location));
            x = endPoint.X;
            y = endPoint.Y;
            AddGeometries("cross", GetCross());
            OnChangedCoordinater(EventArgs.Empty);
        }


        
        public List<IGeometry> GetCross()
        {
            Extent ext = map1.ViewExtents;
            Coordinate[] north = new Coordinate[2]{
                Utils.AzimuthDistC(this.X,this.Y, 0, ext.Width * 0.01),
            Utils.AzimuthDistC(this.X,this.Y, Math.PI, ext.Width * 0.01)
            };
            Coordinate[] east = new Coordinate[2]
            {
                Utils.AzimuthDistC(this.X,this.Y, Math.PI/2, ext.Width * 0.01),
            Utils.AzimuthDistC(this.X,this.Y, 3*Math.PI/2,ext.Width * 0.01)
            };

            List<IGeometry> cross = new List<IGeometry>(){
            new LineString(east),new LineString(north)};
            return cross;
        }


        public double GetValue(Coordinate coor)
        {
            if (_raster == null) return double.NaN;
            return _raster.GetNearestValue(coor);
        }

        public IRaster GetSurface()
        {
            return this._raster; 
        }

        public void SetProjection(ProjectionInfo p)
        {
            map1.Projection = p;
            proj = p;
            CreateAuxiliarLayers();
        }
        private ProjectionInfo proj;

        private void CreateAuxiliarLayers()
        {
            if (cross == null && pointSelect == null && poly == null)
            {
                AddLayers("all");

            }
        }

        private void AddLayers(string type)
        {
            if (type == "cross" || type == "all")
            {
                idcross = new FeatureSet(FeatureType.Line);
                idcross.Projection = proj;
                idcross.Name = "cross";
                IMapLineLayer ml = new MapLineLayer(idcross);
                ml.Symbolizer = new LineSymbolizer();
                ml.Symbolizer.SetFillColor(Color.Red);

                map1.Layers.Add(ml);
            }


            if (type == "point" || type == "all")
            {
                pointSelect = new FeatureSet(FeatureType.Point);
                pointSelect.Projection = proj;
                pointSelect.Name = "point";
                IMapPointLayer mp = new MapPointLayer(pointSelect);
                mp.Symbolizer = new PointSymbolizer();
                mp.Symbolizer.SetSize(new Size2D(5, 5));
                mp.Symbolizer.SetOutline(Color.Blue, 1.0);
                mp.Symbolizer.SetFillColor(Color.Blue);
                map1.Layers.Add(mp);
            }
             if (type == "line" || type == "all")
            {
                cross = new FeatureSet(FeatureType.Line);
                cross.Projection = proj;
                cross.Name = "line";
             IMapLineLayer ml = new MapLineLayer(cross);
             ml.Symbolizer = new LineSymbolizer();
             ml.Symbolizer.SetOutline(Color.Magenta, 1.0);
             map1.Layers.Add(ml);
             }

             if (type == "polygon" || type == "all")
             {
                 poly = new FeatureSet(FeatureType.Polygon);
                 poly.Projection = proj;
                 poly.Name = "polygon";
                 IMapPolygonLayer my = new MapPolygonLayer(poly);
                 my.Symbolizer = new PolygonSymbolizer();
                 my.Symbolizer.SetOutline(Color.Maroon, 1.0);
                 my.Symbolizer.SetFillColor(Color.Transparent);
                 map1.Layers.Add(my);
             }

            
           
            
            
        
        }

        public void AddGeometries(string layer, List<IGeometry> data)
        {
            IFeatureSet lay;

            foreach (IMapLayer ra in map1.GetFeatureLayers())
            {
                if (ra.LegendText == layer)
                {
                    map1.Layers.Remove(ra);
                    break;
                }
            }


            AddLayers(layer);
            
            foreach (IMapLayer ra in map1.GetFeatureLayers())
            {
                if (ra.LegendText == layer)
                {
                    lay = (IFeatureSet)ra.DataSet;
                    lay.Features.Clear();
                    foreach (IGeometry geo in data)
                    {
                        lay.Features.Add(geo);
                    }
                    break;
                }
                //break;    
                
             }
            map1.ResetBuffer();

        
        }

        public void SetSurface(IRaster value)
        { 

                foreach (IMapLayer ra in map1.GetRasterLayers())
                {
                    map1.Layers.Remove(ra);
                }



                this._raster = value;
                    
                 map1.Layers.Insert(map1.Layers.Count,new MapRasterLayer(this._raster));

                 
                    //foreach (IMapLayer ra in map1.GetFeatureLayers())
                    //{

                    //        map1.Layers.Remove(ra);
                    //        map1.Layers.Add(ra);
                    //}
                SchemeRaster();
                map1.ViewExtents = value.Extent;
        }


        public void SetPointLayer(IFeatureSet value)
        {
            IMapLayer mapR = null;
            foreach (IMapLayer ra in map1.GetPointLayers())
            {
               if (ra.LegendText== "DataSetPoints")
                mapR = ra;
            }

            if (mapR != null)
                map1.Layers.Remove(mapR);

            IMapPointLayer mp = new MapPointLayer(value);
            value.Name = "DataSetPoints";
            mp.Symbolizer = new PointSymbolizer();
            mp.Symbolizer.SetSize(new Size2D(7, 7));
            //mp.Symbolizer.Symbols[0].SymbolType= Sym
            mp.Symbolizer.SetOutline(Color.Green, 1.0);
            mp.Symbolizer.SetFillColor(Color.Red);
            map1.Layers.Add(mp);
            map1.ViewExtents = value.Extent;
        }


        public void SetLayer(IFeatureSet value)
        {
            IMapLayer mapR = null;
            foreach (IMapLayer ra in map1.GetPolygonLayers())
            {
                if (ra.LegendText != "point" && ra.LegendText != "line" && ra.LegendText != "polygon" && ra.LegendText != "cross")
                mapR = ra;
            }
            if (mapR != null)
                map1.Layers.Remove(mapR);


            this._polygon = value;

            IMapPolygonLayer mp = new MapPolygonLayer(value);
            mp.Symbolizer = new PolygonSymbolizer();
            mp.Symbolizer.SetOutline(Color.Green, 1.0);
            mp.Symbolizer.SetFillColor(Color.Transparent);
            map1.Layers.Add(mp);

        }

        public IFeatureSet GetLayer()
        {
            return this._polygon;
        }



        private void SchemeRaster()
        {
            IMapRasterLayer layer = null;
            foreach (IMapRasterLayer ra in map1.GetRasterLayers())
            {
                layer = ra;
            }
            if (layer == null || valuesMinMax == null) return;
            double min = valuesMinMax[0];
            double max = valuesMinMax[1];



            ColorScheme scheme = new ColorScheme();

            ColorCategory category2 = new ColorCategory(-100000, min, Color.FromArgb(100, 0, 0), Color.FromArgb(250, 0, 0));
            category2.LegendText = "< " + min.ToString();
            scheme.AddCategory(category2);

            double step = (max - min) / 10;
            int i;
            for (i = 0; i < 10; i++)
            {
                ColorCategory category1 = new ColorCategory((min + (step * i)), (min + ((i + 1) * step)), Color.FromArgb(250 - (i * 20), i * 10, i * 22), Color.FromArgb(250 - (((i + 1) * 20)), (i + 1) * 10, (i + 1) * 22));
                double rmin = Math.Round(min + (step * i), 4);
                double rmax = Math.Round(min + ((i + 1) * step), 4);
                category1.LegendText = rmin.ToString() + " " + rmax.ToString();
                scheme.AddCategory(category1);
            }

            ColorCategory category3 = new ColorCategory(max, 10000000, Color.FromArgb(50, 100, 220), Color.FromArgb(30, 110, 244));
            category2.LegendText = "> " + max.ToString();
            scheme.AddCategory(category3);


            layer.Symbolizer.Scheme = scheme;
            layer.WriteBitmap();
            map1.Refresh();
        }


        private void ZoomIn_Click(object sender, EventArgs e) 
        {
            map1.ZoomIn();
        }
        private void ZoomOut_Click(object sender, EventArgs e)
        {
            map1.ZoomOut();

        }

        private void Pan_Click(object sender, EventArgs e)
        {
            map1.FunctionMode = FunctionMode.Pan;
        }
        private void Identify_Click(object sender, EventArgs e)
        {
            map1.FunctionMode = FunctionMode.Info;
        }

        private void InitializeComponent()
        {
            this.splitContainer1 = new System.Windows.Forms.SplitContainer();
            this.map1 = new DotSpatial.Controls.Map();
            this.uxIdentify = new System.Windows.Forms.Button();
            this.uxPan = new System.Windows.Forms.Button();
            this.uxZoomOut = new System.Windows.Forms.Button();
            this.uxZoomIn = new System.Windows.Forms.Button();
            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
            this.splitContainer1.Panel1.SuspendLayout();
            this.splitContainer1.Panel2.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            this.SuspendLayout();
            // 
            // splitContainer1
            // 
            this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.splitContainer1.Location = new System.Drawing.Point(0, 0);
            this.splitContainer1.Name = "splitContainer1";
            this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
            // 
            // splitContainer1.Panel1
            // 
            this.splitContainer1.Panel1.Controls.Add(this.map1);
            // 
            // splitContainer1.Panel2
            // 
            this.splitContainer1.Panel2.Controls.Add(this.uxIdentify);
            this.splitContainer1.Panel2.Controls.Add(this.uxPan);
            this.splitContainer1.Panel2.Controls.Add(this.uxZoomOut);
            this.splitContainer1.Panel2.Controls.Add(this.uxZoomIn);
            this.splitContainer1.Size = new System.Drawing.Size(344, 305);
            this.splitContainer1.SplitterDistance = 264;
            this.splitContainer1.TabIndex = 0;
            // 
            // map1
            // 
            this.map1.AllowDrop = true;
            this.map1.BackColor = System.Drawing.Color.White;
            this.map1.CollectAfterDraw = false;
            this.map1.CollisionDetection = false;
            this.map1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.map1.ExtendBuffer = false;
            this.map1.FunctionMode = DotSpatial.Controls.FunctionMode.None;
            this.map1.IsBusy = false;
            this.map1.Legend = null;
            this.map1.Location = new System.Drawing.Point(0, 0);
            this.map1.Name = "map1";
            this.map1.ProgressHandler = null;
            this.map1.ProjectionModeDefine = DotSpatial.Controls.ActionMode.Prompt;
            this.map1.ProjectionModeReproject = DotSpatial.Controls.ActionMode.Prompt;
            this.map1.RedrawLayersWhileResizing = false;
            this.map1.SelectionEnabled = true;
            this.map1.Size = new System.Drawing.Size(344, 264);
            this.map1.TabIndex = 0;
            // 
            // uxIdentify
            // 
            this.uxIdentify.Location = new System.Drawing.Point(171, 2);
            this.uxIdentify.Name = "uxIdentify";
            this.uxIdentify.Size = new System.Drawing.Size(30, 23);
            this.uxIdentify.TabIndex = 3;
            this.uxIdentify.Text = "Id";
            this.uxIdentify.UseVisualStyleBackColor = true;
            this.uxIdentify.Click += new System.EventHandler(this.Identify_Click);
            // 
            // uxPan
            // 
            this.uxPan.Location = new System.Drawing.Point(120, 2);
            this.uxPan.Name = "uxPan";
            this.uxPan.Size = new System.Drawing.Size(35, 23);
            this.uxPan.TabIndex = 2;
            this.uxPan.Text = "Pan";
            this.uxPan.UseVisualStyleBackColor = true;
            this.uxPan.Click += new System.EventHandler(this.Pan_Click);
            // 
            // uxZoomOut
            // 
            this.uxZoomOut.Location = new System.Drawing.Point(68, 2);
            this.uxZoomOut.Name = "uxZoomOut";
            this.uxZoomOut.Size = new System.Drawing.Size(36, 23);
            this.uxZoomOut.TabIndex = 1;
            this.uxZoomOut.Text = "Z-";
            this.uxZoomOut.UseVisualStyleBackColor = true;
            this.uxZoomOut.Click += new System.EventHandler(this.ZoomOut_Click);
            // 
            // uxZoomIn
            // 
            this.uxZoomIn.Location = new System.Drawing.Point(18, 2);
            this.uxZoomIn.Name = "uxZoomIn";
            this.uxZoomIn.Size = new System.Drawing.Size(34, 23);
            this.uxZoomIn.TabIndex = 0;
            this.uxZoomIn.Text = "Z+";
            this.uxZoomIn.UseVisualStyleBackColor = true;
            this.uxZoomIn.Click += new System.EventHandler(this.ZoomIn_Click);
            // 
            // OperationsMap
            // 
            this.Controls.Add(this.splitContainer1);
            this.Name = "OperationsMap";
            this.Size = new System.Drawing.Size(344, 305);
            this.splitContainer1.Panel1.ResumeLayout(false);
            this.splitContainer1.Panel2.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
            this.splitContainer1.ResumeLayout(false);
            this.ResumeLayout(false);

        }


        
    }
}
